#! /usr/bin/env python
#coding=utf-8

class TableBuilder(object):
	def __init__(self, cursor, name):
		self._cursor = cursor
		self._name = name

	def getCursor(self):
		return self._cursor

	def createTable(self):
		# drop if exists
		sqlcmd = "drop table if exists %s" % self._name
		self._cursor.execute(sqlcmd)

		# create table
		keys = self.getColumns() + self.getColumnsExtraInfo()

		sqlcmd = "create table %s(%s)" % (self._name, ", ".join(keys))
		#print(sqlcmd)
		self._cursor.execute(sqlcmd)

	# To be overrided
	def getColumns(self):
		return ()

	# To be overrided
	def getKeys(self):
		return ()
	def getColumnsExtraInfo(self):
		return ()

	def _getSqliteVal(self, obj, k):
		if k in obj:
			val = obj[k]
		else:
			val = ""
		if val is None:
			return '"' + str(val) + '"'
		if type(val) in (tuple, list):
			return str(len(val))
		elif isinstance(val, str):
			return '"' + val + '"'
		elif isinstance(val, bool):
			return str(int(val))
		elif isinstance(val, int):
			return str(val)
		return '"' + str(val) + '"'

	def addObjectToDb(self, obj, execute=True, key=False):
		keys = ()
		if key :
			keys = self.getKeys()
		else:
			keys = self.getColumns()

		vals = [self._getSqliteVal(obj, k) for k in keys]
		sqlcmd = "insert into %s (%s) values (%s)" % (self._name, ", ".join(keys), ", ".join(vals))
		#print(sqlcmd)
		if execute:
			self._cursor.execute(sqlcmd)
		return sqlcmd

class ModuleTableBuilder(TableBuilder):
	MEMINFO_COLS = ("processes", "Pss", "swapPss", "Shared_Dirty", "Private_Dirty")
	CHIPSET_SDK_COLS = ("chipsetsdk_DependedBy", "chipsetsdk_symbols", "platformsdk_DependedBy", "platformsdk_symbols", "external_symbols")
	def __init__(self, cursor):
		#TableBuilder.__init__(self, cursor, "modules")
		super(ModuleTableBuilder, self).__init__(cursor, "modules")

	def getColumns(self):
		return ("id", "object_id", "name", "size", "text_size", "data_size", "bss_size", "type", "path",  \
			"provided", "used", "needed", "matched", "duplicated", "unmatched", \
			"deps", "deps_indirect", "deps_total", "depth", "dependedBy", "dependedBy_indirect", "dependedBy_total", "dependedBy_depth", \
			"subsystem", "componentName", "chipset", "third_party", "napi", "innerapi", "sa_id", "modGroup", \
			"deps_internal", "deps_external", "dependedBy_internal", "dependedBy_external", "platformsdk", "platformsdk_indirect", "chipsetsdk", "chipsetsdk_indirect", "hdiType", "labelPath", "shlib_type", "version_script", "innerapi_tags", "innerapi_declared") + \
		ModuleTableBuilder.MEMINFO_COLS + ModuleTableBuilder.CHIPSET_SDK_COLS

class DepedenceiesTableBuilder(TableBuilder):
	def __init__(self, cursor):
		TableBuilder.__init__(self, cursor, "dependencies")

	def getColumns(self):
		#return ("binary_id", "library_id", "direct")
 		return ("caller_id", "callee_id", "calls", "external", "platformsdk", "chipsetsdk")

	def getColumnsExtraInfo(self):
		return ("id INTEGER PRIMARY KEY", "FOREIGN KEY(caller_id) REFERENCES modules(id)", "FOREIGN KEY(callee_id) REFERENCES modules(id)")

class SymbolsTableBuilder(TableBuilder):
	def __init__(self, cursor):
		TableBuilder.__init__(self, cursor, "symbols")

	def getColumns(self):
		return ("parent_id", "name", "weak", "version", "library", "demangle", "calls")

	def getColumnsExtraInfo(self):
		return ("id INTEGER PRIMARY KEY", "FOREIGN KEY(parent_id) REFERENCES modules(id)")

class SymbolNamesTableBuilder(TableBuilder):
	def __init__(self, cursor):
		TableBuilder.__init__(self, cursor, "symbol_names")

	def getColumns(self):
		return ("name", "demangle", "count", "calls")

class UndefinedSymbolsTableBuilder(TableBuilder):
	def __init__(self, cursor):
		TableBuilder.__init__(self, cursor, "undefines")

	def getColumns(self):
		return ("parent_id", "name", "weak", "version", "library", "demangle")

	def getColumnsExtraInfo(self):
		return ("FOREIGN KEY(parent_id) REFERENCES modules(id)", )

class CallsTableBuilder(TableBuilder):
	def __init__(self, cursor):
		TableBuilder.__init__(self, cursor, "calls")

	def getColumns(self):
		return ("caller_id", "callee_id", "symbol_id", "dependence_id")

	def getColumnsExtraInfo(self):
		return ("FOREIGN KEY(caller_id) REFERENCES modules(id)", "FOREIGN KEY(callee_id) REFERENCES modules(id)", "FOREIGN KEY(symbol_id) REFERENCES symbols(id)", "FOREIGN KEY(dependence_id) REFERENCES dependencies(id)")

class IndirectsTableBuilder(TableBuilder):
	def __init__(self, cursor):
		TableBuilder.__init__(self, cursor, "indirects")

	def getColumns(self):
		return ("caller_id", "callee_id", "external")

	def getColumnsExtraInfo(self):
		return ("id INTEGER PRIMARY KEY", "FOREIGN KEY(caller_id) REFERENCES modules(id)", "FOREIGN KEY(callee_id) REFERENCES modules(id)")

if __name__ == '__main__':
	import sqlite3

	conn = sqlite3.connect("symdb.db")
	cursor = conn.cursor()

	builder = ModuleTableBuilder(cursor)
	builder.createTable()

	conn.commit()
	cursor.close()
	conn.close()
